import 'dart:convert';

import 'package:flutter/cupertino.dart';
import 'package:flutter/services.dart';
import 'package:t3_map/address_select.dart';
import 'core/t3_annotation.dart';
import 'core/t3_location.dart';
import 't3_map_event_stream.dart';
import 'core/t3_polyline.dart';

part 't3_map_controller_annotation.dart';
part 't3_map_controller_polyline.dart';


enum T3UserTrackingMode {
  none(0),
  follow(1),
  followWithHeading(2);
  
  final int value;

  const T3UserTrackingMode(this.value);
}


/// 地图的操作类。可添加点线面等常规操作
class T3MapController {

  late String _mapId;
  String get mapId => _mapId;

  late MethodChannel _methodChannel;
  final T3MapEventStream _eventStream = T3MapEventStream();
  T3MapEventStream get eventStream => _eventStream;

  final List<T3Annotation> _annotations = [];
  List<T3Annotation> get annotations => _annotations;

  final List<T3Polyline> _polylines = [];
  List<T3Polyline> get polylines => _polylines;

  /// 当前的位置数据
  T3MapLocation? userLocation;

  ///地图的视图锚点。坐标系归一化，(0, 0)为MAMapView左上角，(1, 1)为右下角。默认为(0.5, 0.5)，即当前地图的视图中心
  Offset _screenAnchor = const Offset(0.5, 0.5);

  Offset get screenAnchor => _screenAnchor;
  set screenAnchor(Offset point) {
    final json = {'offset': {'x': point.dx, 'y': point.dy}};
    _methodChannel.invokeMethod('map#screenAnchor', jsonEncode(json));
    _screenAnchor = point;
  }

  /// 是否显示用户位置
  /// note: ** 含有默认值的属性需要确保和原生一致
  bool _showsUserLocation = false;

  bool get showsUserLocation => _showsUserLocation;
  set showsUserLocation(bool visible) {
    final json = {"visible": visible};
    _methodChannel.invokeMethod('map#showsUserLocation', jsonEncode(json));
    _showsUserLocation = visible;
  }

  /// 当前位置在地图中是否可见
  Future<bool> get userLocationVisible => _getUserLocationVisible();

  /// 用户定位位置的模式, 注意：在follow模式下，设置地图中心点、设置可见区域、滑动手势、选择annotation操作会取消follow模式，
  /// 并触发 - (void)mapView:(MAMapView *)mapView didChangeUserTrackingMode:(MAUserTrackingMode)mode animated:(BOOL)animated;
  /// note: ** 含有默认值的属性需要确保和原生一致
  T3UserTrackingMode _userTrackingMode = T3UserTrackingMode.none;
  
  T3UserTrackingMode get userTrackingMode => _userTrackingMode;
  set userTrackingMode(T3UserTrackingMode mode) {
    final json = {"mode": mode.value, 'animated': false};
    _methodChannel.invokeMethod('map#userTrackingMode', jsonEncode(json));
    _userTrackingMode = mode;
  }

  /// 当前地图缩放级别,缩放级别（默认3-19，有室内地图时为3-20）
  double _zoomLevel = 17;
  
  double get zoomLevel => _zoomLevel;
  set zoomLevel(double level) {
    final json = {"level": level, 'animated': false};
    _methodChannel.invokeMethod('map#mapViewZoomLevel', jsonEncode(json));
    _zoomLevel = level;
  }

  /// 地图中心点
  T3LocationCoordinate2D? _centerCoordinate;
  T3LocationCoordinate2D? get centerCoordinate => _centerCoordinate;


  /// 地图是否初始化完成
  bool _mapDidInit = false;
  bool get mapDidInit => _mapDidInit;

  T3MapController() {
    _mapId = hashCode.toString();
    _methodChannel = MethodChannel('t3_map_flutter_map_$mapId');
    _methodChannel.setMethodCallHandler(_handleMethodCall);

    //TODO: 这个地方要测试要释放的问题
    eventStream.onMapInitCompleted().listen((event) {
      _mapDidInit = true;
      //从原生获取初始centerCoordinate，和channel的通信，必须在onMapInitCompleted之后完成，否则可能会出现原生的channel还未创建完毕
      _getCenterCoordinate().then((value) => _centerCoordinate = value);
    });

    //实时同步zoomLevel和centerCoordinate
    eventStream.regionChanged().listen((event) {
      _zoomLevel = event.value.zoomLevel;
      _centerCoordinate = event.value.centerCoordinate;
    });
  }

  ///定位用户位置的模式
  void setupUserTrackingMode(T3UserTrackingMode mode ,{bool animated = false}) {
    final json = {"mode": mode.value, 'animated': animated};
    _methodChannel.invokeMethod('map#userTrackingMode', jsonEncode(json));
    _userTrackingMode = mode;
  }

  ///是否显示用户位置
  ///native返回数据
  ///```json
  /// {
  ///   "visible": false
  /// }
  ///```
  Future<bool> _getUserLocationVisible() async {
    final result = await _methodChannel.invokeMethod('map#userLocationVisible');
    if (result is String) {
      try {
        final json = jsonDecode(result);
        final visible = json['visible'];
        if (visible is bool) {
          return visible;
        }
        else {
          return false;
        }
      } catch (e) {
        rethrow;
      }
    }
    else {
      return false;
    }
  }

  /// 获取地图中心点数据
  Future<T3LocationCoordinate2D?> _getCenterCoordinate() async {
    final result = await _methodChannel.invokeMethod('map#mapViewGetCenterCoordinate');
    if (result is String) {
      try {
        final json = jsonDecode(result);
        final longitude = json['longitude'];
        final latitude = json['latitude'];
        if (longitude is num && latitude is num) {
          return T3LocationCoordinate2D(longitude: longitude.toDouble(), latitude: latitude.toDouble());
        }
        else {
          return null;
        }
      } catch (e) {
        return null;
      }
    }
    else {
      return null;
    }
  }

  /// 设置地图缩放级别
  void setupMapViewZoomLevel({required double level, required bool animated}) {
    final json = {"level": level, 'animated': animated};
    _methodChannel.invokeMethod('map#mapViewZoomLevel', jsonEncode(json));
    _zoomLevel = level;
  }

  /// 设置地图中心点
  void setupMapViewCenter({required T3LocationCoordinate2D coordinate, required bool animated}) {
    final json = {"coordinate": coordinate.toJson(), 'animated': animated};
    _methodChannel.invokeMethod('map#mapViewCenter', jsonEncode(json));
    _centerCoordinate = coordinate;
  }

  /// 在可视区域内显示Polyline + Annotations
  void showPolylinesAndAnnotations({required List<T3Polyline> polylines, required List<T3Annotation> annotations, EdgeInsets edgeInsets = EdgeInsets.zero, required bool animated}) {
    final json = {
      "polylines": polylines.map((e) => e.toJson()).toList(),
      "annotations": annotations.map((e) => e.toJson()).toList(),
      "edgeInsets": _edgeInsetsToJson(edgeInsets),
      "animated": animated
      };
    _methodChannel.invokeMethod('map#showPolylinesAndAnnotations', jsonEncode(json));
  }


  // ///截屏
  // Future<Uint8List?> takeSnapshot({
  //   required int mapId,
  // }) {
  //   return _methodChannel.invokeMethod<Uint8List>('map#takeSnapshot');
  // }


  /// 用于原生地图向dart发送事件
  Future<dynamic> _handleMethodCall(MethodCall call) async {
    return _eventStream.handleMethodCall(call);
  }

  Map<String, double> _edgeInsetsToJson(EdgeInsets edgeInsets) {
    return {
      "top":edgeInsets.top,
      "bottom":edgeInsets.bottom,
      "left":edgeInsets.left,
      "right":edgeInsets.right,
    };
  }

  Map<String, double> _rectToJson(Rect rect) {
    return {
      "left": rect.left, 
      "top": rect.top, 
      "width": rect.width, 
      "height": rect.height
    };
  }
}